home *** CD-ROM | disk | FTP | other *** search
/ SPACE 1 / SPACE - Library 1 - Volume 1.iso / games / 223 / accent / accent.mod next >
Text File  |  1988-02-07  |  26KB  |  845 lines

  1. (******************************************************************)
  2. (**)               MODULE Accent; (* 87Nov29 - kbad *)          (**)
  3. (**   based on accent.c developed by John Stern of Ampex Corp.   **)
  4. (******************************************************************)
  5. (* Copyright 1987,1988 Ken Badertscher
  6.  * Permission is granted to use this program and source code,
  7.  * however it may NOT be used or modified for any commercial gain.
  8.  * The author disclaims responsibility for any damages resulting
  9.  * from the use or misuse of this program, and disclaims liability
  10.  * for losses of any kind or nature, financial or otherwise,
  11.  * incurred as a result of the use of this software.
  12.  *)
  13. (******************************************************************)
  14.  *                             IMPORTs                            *)
  15. (*================================================================*)
  16.  
  17. FROM SYSTEM IMPORT ADDRESS, REG, INLINE;
  18.  
  19. IMPORT ASCII;
  20.  
  21. FROM String IMPORT
  22. (*PROC*)    InitStringModule, Concat, Pos, Assign, Insert;
  23.  
  24. FROM Terminal IMPORT
  25. (*PROC*)    WriteString, Read, Write, WriteLn;
  26.  
  27. FROM BasePage IMPORT
  28. (*PROC*)    NumberOfArguments, GetArgument;
  29.  
  30. FROM FileSystem IMPORT
  31. (*TYPE*)    File, Response,
  32. (*PROC*)    Lookup, Close, Delete, Reset, ReadChar, WriteChar,
  33.             Length, SetRead, Doio;
  34.  
  35. FROM Heap IMPORT
  36. (*PROC*)    CreateHeap, Allocate, DeAllocate;
  37.  
  38. FROM Random IMPORT
  39. (*PROC*)    RandomInt;
  40.  
  41. FROM AccentStrings IMPORT
  42. (*CONST*)   PAGEWIDTH,
  43. (*TYPE*)    AccentString,
  44. (*VAR*)     vowel, cocknie, nerdism, curse, censor, article;
  45.  
  46. IMPORT AccentObjects;
  47.  
  48. (******************************************************************)
  49. (*                      Global declarations                       *)
  50. (*================================================================*)
  51.  
  52. CONST
  53.     BUFSIZE     = 512;
  54.  
  55. (*----------------------------------------------------------------*)
  56. (* local Malloc definitions used to get available memory          *)
  57.     D0          = 0;
  58.     pop         = 4FEFH; (* lea x(sp),sp *)
  59.     TrapGEMDOS  = 4E41H; (* trap #1      *)
  60.     available   = -1D;
  61.     malloc      = 48H;
  62.  
  63. PROCEDURE Malloc(amt: LONGINT; fnID: INTEGER); CODE TrapGEMDOS;
  64.  
  65. (*----------------------------------------------------------------*)
  66.  
  67. TYPE
  68.     Buf         = ARRAY [0..BUFSIZE] OF CHAR;
  69.     CapsOpts    = (STARTWORD, NOCAPS, ONECAP, ALLCAPS);
  70.  
  71. VAR
  72.     (* PROC vars used in 'accent' array for multiple accents *)
  73.     Japanese, Chinese, German, Cockney, Italian, Stutter,
  74.     PigLatin, Lisp, Nerd, Obscene, Uncensored, Nroff : PROC;
  75.  
  76.     (* accent flags, procedures, and flag descriptions *)
  77.     accent  : ARRAY [0..13] OF
  78.                 RECORD
  79.                   option  : CHAR;
  80.                   func    : PROC;
  81.                   descrip : AccentString;
  82.                 END;
  83.  
  84.     (* current set of accent options *)
  85.     opts        : AccentString;
  86.  
  87.     (* temporaries used to hold individual words *)
  88.     buf,
  89.     tmpbuf      : Buf;
  90.  
  91.     (* capitalization flags *)
  92.     caps        : CapsOpts;
  93.  
  94.     (* word terminator and last character read *)
  95.     punc,ch     : CHAR;
  96.  
  97.     (* current argument, total arguments *)
  98.     arg,nargs   : CARDINAL;
  99.  
  100.     (* various globals, ptr holds current index into buf, and     *)
  101.     (* cursepos holds position of beginning of curse for DoCensor *)
  102.     s,c,n,ptr,
  103.     cursepos    : INTEGER;
  104.  
  105.     (* various flags -- if TRUE: *)
  106.     whocares,
  107.     prevLF,     (* last char read was an EOL            *)
  108.     showForms,  (* program was called from the desktop  *)
  109.     cancel,     (* user canceled from file-selector     *)
  110.     redir,      (* redirect output to printer or disk   *)
  111.     nrofflag,   (* nroff mode in effect                 *)
  112.     pass,       (* skip current line in nroff mode      *)
  113.     escchar     (* word started with a '\' (nroff esc)  *)
  114.             : BOOLEAN;
  115.  
  116.     (* command line arguments *)
  117.     args        : ARRAY [1..10] OF AccentString;
  118.  
  119.     (* input and output file variables *)
  120.     infile,
  121.     outfile     : File;
  122.     maxFileSize,
  123.     infileLen,
  124.     amtToAlloc  : LONGINT;
  125.     Pinfile,
  126.     PinfileCH   : ADDRESS;
  127.  
  128. (******************************************************************)
  129. (*                      Some useful procedures                    *)
  130. (*================================================================*)
  131.  
  132. PROCEDURE GetCH;
  133.   BEGIN
  134.     ch := VAL(CHAR,PinfileCH^);
  135.     INC(PinfileCH);
  136.     DEC(infileLen);
  137.   END GetCH;
  138.  
  139. (*----------------------------------------------------------------*)
  140.  
  141. PROCEDURE StrLength(s: ARRAY OF CHAR): INTEGER;
  142.   VAR l: INTEGER;
  143.   BEGIN l := 0;
  144.     WHILE ( l <= HIGH(s) ) AND ( s[l] # 0C ) DO INC(l) END;
  145.     RETURN l
  146.   END StrLength;
  147.  
  148. (*----------------------------------------------------------------*)
  149.  
  150. PROCEDURE IsVowel(ch: CHAR): BOOLEAN;
  151.   VAR i: INTEGER;
  152.   BEGIN
  153.     FOR i := 0 TO HIGH(vowel) DO
  154.       IF (ch = vowel[i,0]) THEN RETURN TRUE END;
  155.     END;
  156.     RETURN FALSE
  157.   END IsVowel;
  158.  
  159. (*----------------------------------------------------------------*)
  160.  
  161. PROCEDURE IsArticle(str: ARRAY OF CHAR): BOOLEAN;
  162.   VAR i,len: INTEGER;
  163.   BEGIN
  164.     FOR i := 0 TO HIGH(article) DO
  165.       len := StrLength(article[i]);
  166.       IF ( StrLength(str) = len ) THEN
  167.         WHILE (len > -1) AND ( article[i,len] = str[len] ) DO
  168.           DEC(len)
  169.         END;
  170.         IF len = -1 THEN RETURN TRUE END;
  171.       END;
  172.     END;
  173.     RETURN FALSE
  174.   END IsArticle;
  175.  
  176. (*----------------------------------------------------------------*)
  177.  
  178. PROCEDURE Strip(VAR from: ARRAY OF CHAR;
  179.         startingAt, howMany : INTEGER);
  180.   BEGIN 
  181.     WHILE from[startingAt+howMany] # 0C DO
  182.       from[startingAt] := from[startingAt+howMany];
  183.       INC(startingAt);
  184.     END;
  185.     from[startingAt] := 0C;
  186.   END Strip;
  187.  
  188. (*----------------------------------------------------------------*)
  189.  
  190. PROCEDURE WaitForKey(prompt: ARRAY OF CHAR);
  191.   VAR ch: CHAR;
  192.   BEGIN
  193.     WriteLn;
  194.     Write(33C);Write('p');
  195.     WriteString(prompt);
  196.     Write(33C);Write('q');
  197.     Read(ch);
  198.   END WaitForKey;
  199.  
  200. (******************************************************************)
  201. (**)                    MODULE WrapWriting;                     (**)
  202. (**            perorms word-wrapping of Accent output            **)
  203. (*================================================================*)
  204.  
  205. IMPORT
  206. (*PROC*)    StrLength, Concat, Write, WriteLn, WriteChar, 
  207. (*TYPE*)    Buf,
  208. (*VAR*)     redir, outfile,
  209. (*CONST*)   PAGEWIDTH;
  210.  
  211. EXPORT WrapWrite;
  212.  
  213. CONST
  214.     SPACE = ' ';
  215.     CR = 15C;
  216.     LF = 12C;
  217. VAR
  218.     lineBuf : Buf;      (* holds current line       *)
  219.     curPos  : INTEGER;  (* current position in line *)
  220.  
  221. PROCEDURE WrapWrite(word: ARRAY OF CHAR;
  222.                     flush: BOOLEAN ): BOOLEAN;
  223. (*  Output 'word' with word-wrapping to console, and (IF redir)
  224.  * to 'outfile'.  IF flush, then put out the current line.
  225.  * Should return FALSE on a write error to outfile, but in the
  226.  * interest of speed, it doesn't.
  227.  *)
  228.   VAR newPos,wordLen: INTEGER;
  229.   BEGIN
  230.     wordLen := StrLength(word);
  231.     newPos := curPos + wordLen;
  232.     IF ( flush ) OR
  233.        ( newPos > PAGEWIDTH ) OR
  234.        ( newPos > HIGH(lineBuf) ) THEN
  235.       newPos := 0;
  236.       WHILE lineBuf[newPos] # 0C DO
  237.         Write(lineBuf[newPos]);
  238.         IF redir THEN WriteChar(outfile,lineBuf[newPos]) END;
  239.         INC(newPos);
  240.       END;
  241.       WriteLn;
  242.       IF redir THEN WriteChar(outfile,CR); WriteChar(outfile,LF) END;
  243.       curPos := 0;
  244.       lineBuf := "";
  245.     END;
  246.     Concat(lineBuf,word,lineBuf);
  247.     curPos := curPos + wordLen;
  248.     RETURN TRUE
  249.   END WrapWrite;
  250.  
  251. BEGIN
  252.   curPos := 0;
  253. END WrapWriting;
  254.  
  255. (******************************************************************)
  256. (*                  "Accent-ization" procedures                   *)
  257. (*================================================================*)
  258.  
  259. PROCEDURE DoJapanese;
  260.   VAR s: INTEGER;
  261.   BEGIN s := 0;
  262.     WHILE (buf[s] # 0C) DO
  263.       IF (buf[s] = 'l') THEN buf[s] := 'r' END;
  264.       INC(s);
  265.     END;
  266.   END DoJapanese;
  267.  
  268. (*----------------------------------------------------------------*)
  269.  
  270. PROCEDURE DoChinese;
  271.   VAR s: INTEGER;
  272.   BEGIN s := 0;
  273.     WHILE (buf[s] # 0C) DO
  274.       IF(buf[s] = 'r') THEN buf[s] := 'l' END;
  275.       INC(s);
  276.     END;
  277.   END DoChinese;
  278.  
  279. (*----------------------------------------------------------------*)
  280.  
  281. PROCEDURE DoGerman;
  282.   VAR s: INTEGER;
  283.   BEGIN s := 0;
  284.     WHILE (buf[s] # 0C) DO
  285.       CASE buf[s] OF
  286.         'c' : IF (IsVowel(buf[s+1])) AND
  287.                 ( (s = 0) OR (IsVowel(buf[s-1])) ) THEN buf[s] := 'k' END
  288.       | 'd' : IF (buf[s+1] = 0C) THEN buf[s] := 't' END
  289.       | 'g' : IF (buf[s+1] = 0C) THEN buf[s] := 'k' END
  290.       | 'p' : IF (buf[s+1] = 'h') THEN
  291.                 buf[s] := 'f'; Strip(buf,s+1,1) END
  292.       | 's' : IF (IsVowel(buf[s+1])) AND
  293.                 ( (s = 0) OR (IsVowel(buf[s-1])) ) THEN buf[s] := 'z' END
  294.       | 't' : IF (s = 0) AND (buf[s+1] = 'h') THEN
  295.                 buf[s] := 'z'; Strip(buf,s+1,1) END
  296.       | 'v' : buf[s] := 'f'
  297.       | 'w' : buf[s] := 'v'
  298.       ELSE
  299.       END;(*CASE*)
  300.       INC(s);
  301.     END;(*WHILE*)
  302.   END DoGerman;
  303.  
  304. (*----------------------------------------------------------------*)
  305.  
  306. PROCEDURE DoItalian;
  307.   VAR s: INTEGER;
  308.   BEGIN s := 0;
  309.     WHILE (buf[s] # 0C) DO
  310.       CASE buf[s] OF
  311.         'h' : IF (s = 0) THEN buf[s] := "'" END
  312.       | 't' : IF (buf[s+1] = 'h') THEN Strip(buf,s+1,1) END
  313.       ELSE END;
  314.       INC(s);
  315.     END;
  316.     IF ( (RandomInt(0,2) = 2) AND (StrLength(buf) > 2) ) THEN
  317.       IF NOT( IsVowel(buf[s-1]) ) THEN
  318.         buf[s] := vowel[RandomInt(0,HIGH(vowel)),0]; INC(s);
  319.         buf[s] := 0C;
  320.       ELSIF (buf[s-1] = 'e') AND NOT( IsVowel(buf[s-2]) ) THEN
  321.         buf[s-1] := vowel[RandomInt(0,HIGH(vowel)),0];
  322.       END;
  323.     END;
  324.   END DoItalian;
  325.  
  326. (*----------------------------------------------------------------*)
  327.  
  328. PROCEDURE DoCockney;
  329.   BEGIN
  330.     IF ( IsArticle(buf) ) AND ( ODD(RandomInt(0,1)) ) THEN
  331.       Concat(buf," ",buf);
  332.       Concat(buf,cocknie[RandomInt(0,HIGH(cocknie))],buf);
  333.     END;
  334.     IF (buf[0] = 'h') AND ( IsVowel(buf[1]) ) THEN buf[0] := "'" END;
  335.   END DoCockney;
  336.  
  337. (*----------------------------------------------------------------*)
  338.  
  339. PROCEDURE DoStutter;
  340.   VAR tmpptr,ptr,stuts : INTEGER;
  341.   BEGIN tmpptr := 0; ptr := 0;
  342.  
  343.     IF ( ASCII.CharIsAlpha(buf[0]) ) AND
  344.        (StrLength(buf) > 2) AND (RandomInt(1,4) = 1)  THEN
  345.  
  346.       (* search for end of consonants *)
  347.       WHILE NOT( IsVowel(buf[ptr]) ) AND (buf[ptr] # 0C) DO
  348.         tmpbuf[tmpptr] := buf[ptr]; INC(tmpptr); INC(ptr);
  349.       END;
  350.  
  351.       tmpbuf[tmpptr] := 0C;
  352.       IF (buf[ptr] # 0C) THEN (* not all consonants *)
  353.         tmpptr := RandomInt(2,5);
  354.         FOR stuts := tmpptr TO 1 BY -1 DO
  355.           Insert(tmpbuf,buf,ptr);
  356.         END;(*FOR*)
  357.       END;(*IF not all consonants*)
  358.  
  359.     END;(*IF IsAlpha*)
  360.   END DoStutter;
  361.  
  362. (*----------------------------------------------------------------*)
  363.  
  364. PROCEDURE DoLisp;
  365.   VAR s: INTEGER;
  366.   BEGIN s := 0;
  367.     WHILE (buf[s] # 0C) DO
  368.       IF (buf[s] = 's') THEN buf[s] := 't'; Insert('h',buf,s+1) END;
  369.       INC(s)
  370.     END
  371.   END DoLisp;
  372.  
  373. (*----------------------------------------------------------------*)
  374.  
  375. PROCEDURE DoNerd;
  376.   BEGIN
  377.     IF ( (IsArticle(buf)) OR (punc = ',') ) AND
  378.        ( ODD(RandomInt(0,1)) ) THEN
  379.       Concat(buf,", ",buf);
  380.       Concat(buf,nerdism[RandomInt(0,HIGH(nerdism))],buf);
  381.       (* add trailing comma if followed by space *)
  382.       IF (punc = ' ') THEN Concat(buf,",",buf) END;
  383.     END
  384.   END DoNerd;
  385.  
  386. (*----------------------------------------------------------------*)
  387.  
  388. PROCEDURE DoPigLatin;
  389.   VAR s, ptr, tmpptr : INTEGER;
  390.   BEGIN ptr := 0; tmpptr := 0;
  391.     IF NOT( ASCII.CharIsAlpha(buf[0]) ) THEN RETURN END;
  392.     IF IsVowel(buf[0]) THEN Concat (buf,"way", buf); RETURN END;
  393.     WHILE NOT( IsVowel(buf[ptr]) ) AND (buf[ptr] # 0C) DO
  394.       (* search for consonants *)
  395.       tmpbuf[tmpptr] := buf[ptr]; INC(tmpptr); INC(ptr);
  396.     END;
  397.     tmpbuf[tmpptr] := 0C;
  398.     Strip(buf,0,ptr);
  399.     Concat(buf,tmpbuf,buf);
  400.     Concat(buf,"ay",buf);
  401.   END DoPigLatin;
  402.  
  403. (*----------------------------------------------------------------*)
  404.  
  405. PROCEDURE DoUncensored;
  406.   BEGIN 
  407.  
  408.     cursepos := 0;
  409.     tmpbuf := " ";
  410.     IF ( IsArticle(buf) ) THEN
  411.       Concat(tmpbuf,curse[RandomInt(0,HIGH(curse))],tmpbuf);
  412.     ELSIF ( (StrLength(buf) = 2) AND
  413.             (buf[0] = 'a') AND (buf[1] = 'n') ) AND
  414.           ( ODD(RandomInt(0,1)) ) THEN
  415.       Concat(tmpbuf,"asshole",tmpbuf);
  416.     ELSE RETURN
  417.     END;
  418.     
  419.     cursepos := VAL(INTEGER,StrLength(buf));
  420.     Concat(buf,tmpbuf,buf);
  421.  
  422.   END DoUncensored;
  423.  
  424. (*----------------------------------------------------------------*)
  425.  
  426. PROCEDURE DoObscene;
  427.   VAR n: INTEGER;
  428.   BEGIN
  429.  
  430.     DoUncensored;
  431.     IF (cursepos # 0) THEN
  432.       tmpbuf := buf;
  433.       INC(cursepos);
  434.       WHILE (buf[cursepos] # 0C) DO
  435.         IF ( ASCII.CharIsAlpha(tmpbuf[cursepos-2]) ) AND
  436.            ( ASCII.CharIsAlpha(tmpbuf[cursepos-1]) ) AND
  437.            ( ASCII.CharIsAlpha(tmpbuf[cursepos]  ) ) AND
  438.            ( ASCII.CharIsAlpha(tmpbuf[cursepos+1]) ) AND
  439.            ( ASCII.CharIsAlpha(tmpbuf[cursepos+2]) ) THEN
  440.           buf[cursepos] := censor[ RandomInt(0,HIGH(censor)) , 0 ];
  441.         END;
  442.         INC(cursepos);
  443.       END; (*WHILE*)
  444.     END; (*IF (cursepos # 0)*)
  445.  
  446.   END DoObscene;
  447.  
  448. (*----------------------------------------------------------------*)
  449.  
  450. PROCEDURE DoNroff;
  451.   BEGIN
  452.     nrofflag := TRUE;
  453.   END DoNroff;
  454.  
  455. (******************************************************************)
  456. (*                  Initialize accent array                       *)
  457. (*----------------------------------------------------------------*)
  458.  
  459. PROCEDURE InitAccent;
  460.   BEGIN
  461.  
  462.     Japanese    := DoJapanese;
  463.     Chinese     := DoChinese;
  464.     German      := DoGerman;
  465.     Italian     := DoItalian;
  466.     PigLatin    := DoPigLatin;
  467.     Cockney     := DoCockney;
  468.     Stutter     := DoStutter;
  469.     Lisp        := DoLisp;
  470.     Nerd        := DoNerd;
  471.     Obscene     := DoObscene;
  472.     Uncensored  := DoUncensored;
  473.     Nroff       := DoNroff;
  474.  
  475.     WITH accent[0] DO
  476.       option := 'J'; func := Japanese; descrip := '(apanese)';
  477.     END;
  478.     WITH accent[1] DO
  479.       option := 'C'; func := Chinese; descrip := '(hinese)';
  480.     END;
  481.     WITH accent[2] DO
  482.       option := 'G'; func := German; descrip := '(erman)';
  483.     END;
  484.     WITH accent[3] DO
  485.       option := 'I'; func := Italian; descrip := '(talian)';
  486.     END;
  487.     WITH accent[4] DO
  488.       option := 'P'; func := PigLatin; descrip := '(ig Latin)';
  489.     END;
  490.     WITH accent[5] DO
  491.       option := 'K'; func := Cockney; descrip := '(cocKney)';
  492.     END;
  493.     WITH accent[6] DO
  494.       option := 'S'; func := Stutter; descrip := '(tutter)';
  495.     END;
  496.     WITH accent[7] DO
  497.       option := 'L'; func := Lisp; descrip := '(isp)';
  498.     END;
  499.     WITH accent[8] DO
  500.       option := 'D'; func := Nerd; descrip := '(nerD)';
  501.     END;
  502.     WITH accent[9] DO
  503.       option := 'O'; func := Obscene; descrip := '(bscene/censored)';
  504.     END;
  505.     WITH accent[10] DO
  506.       option := 'U'; func := Uncensored; descrip := '(ncensored)';
  507.     END;
  508.     WITH accent[11] DO
  509.       option := 'R'; func := Nroff; descrip := '(andom accent)';
  510.     END;
  511.     WITH accent[12] DO
  512.       option := 'N'; func := Nroff; descrip := '(pass Nroff commands)';
  513.     END;
  514.     WITH accent[13] DO
  515.       option := 10C; func := Nroff; descrip := ' file1 [ file2 ... ]';
  516.     END;
  517.  
  518.   END InitAccent;    
  519.     
  520. (******************************************************************)
  521. (*              Use dialogs to get args and files                 *)
  522. (*----------------------------------------------------------------*)
  523.  
  524. PROCEDURE DoForms;
  525.   BEGIN
  526.     (* get input file, terminate program if user selects 'cancel' *)
  527.     cancel := TRUE;
  528.     AccentObjects.GetFile(' Select file to "accent"... ', cancel, args[2]);
  529.     IF cancel THEN AccentObjects.GEMTerm END;
  530.  
  531.     (* get accent options *)
  532.     AccentObjects.GetArgs(args[1]);
  533.  
  534.     (* get output file (if cancel, then just output to screen)    *)
  535.     AccentObjects.GetFile(' Select output file... ', cancel, args[3]);
  536.     redir := ~cancel;
  537.     showForms := TRUE;
  538.     IF redir THEN
  539.       Lookup(outfile, args[3], TRUE);
  540.       IF outfile.res # done THEN
  541.         WriteString('Error opening '); WriteString(args[3]); 
  542.         WaitForKey(' Press a key... ');
  543.         AccentObjects.GEMTerm
  544.       ELSIF ~outfile.new THEN
  545.         Delete(outfile);
  546.         Lookup(outfile, args[3], TRUE);
  547.       END;
  548.     END;
  549.     
  550.     nargs := 2;
  551.   END DoForms;
  552.  
  553. (******************************************************************)
  554. (*                  Check argument validity                       *)
  555. (*----------------------------------------------------------------*)
  556. (* this procedure will only allow the 'uncensored' option if      *)
  557. (* specifically requested on the command line. (i.e. NOT from the *)
  558. (* GEM shell... sorry, kids!                                      *)
  559.  
  560. PROCEDURE CheckArgs(): BOOLEAN;
  561.   VAR optnum: INTEGER;
  562.   BEGIN optnum := 0;
  563.     arg := 1;
  564.     WHILE (arg <= nargs) AND
  565.           (args[arg,0] = '-') DO (* stop at first non-flag argument*)
  566.  
  567.       c := 1;
  568.       WHILE (args[arg,c] # 0C) DO
  569.         args[arg,c] := CAP(args[arg,c]);
  570.         n := 0;
  571.         WHILE (n <= HIGH(accent)) AND (args[arg,c] # accent[n].option) DO
  572.           INC(n);
  573.         END;
  574.         IF n > HIGH(accent) THEN
  575.           WriteString('Illegal option '); Write(args[arg,c]); WriteLn;
  576.           RETURN FALSE;
  577.         ELSE
  578.           IF args[arg,c] = 'R' THEN (* select random argument   *)
  579.             REPEAT
  580.               args[arg,c] := accent[RandomInt(0,HIGH(accent)-3)].option
  581.             UNTIL args[arg,c] # 'U' (* but not 'uncensored'     *)
  582.           END;
  583.           opts[optnum] := args[arg,c]; INC(optnum);
  584.         END;
  585.         INC(c);
  586.       END;
  587.  
  588.       INC(arg);
  589.     END;
  590.     opts[optnum] := 0C;
  591.     RETURN TRUE
  592.  
  593.   END CheckArgs;
  594.  
  595. (******************************************************************)
  596. (*                         MAIN routine                           *)
  597. (*================================================================*)
  598.  
  599. BEGIN (*Accent*)
  600.  
  601.   (* find out how much memory we have to play with *)
  602.   Malloc(available,malloc);
  603.   INLINE(pop,6);
  604.   maxFileSize := REG(D0);
  605.   (* leave room for the resource *)
  606.   maxFileSize := maxFileSize - 32767D;
  607.   (* make the heap or die *)
  608.   IF NOT( CreateHeap(maxFileSize,TRUE) ) THEN
  609.     n := AccentObjects.DoAlert(1,"[3][Memory allocation error][oh, my]");
  610.     AccentObjects.GEMTerm;
  611.   END;
  612.  
  613.   (* init some variables *)
  614.   nrofflag := FALSE;
  615.   redir := FALSE;
  616.   showForms := FALSE;
  617.  
  618.   InitStringModule;
  619.   InitAccent;
  620.  
  621.   punc := ' ';
  622.   buf := "";
  623.  
  624.   nargs := NumberOfArguments();
  625.   arg := 1;
  626.   WHILE (arg <= nargs) DO
  627.     GetArgument(arg, args[arg]);
  628.     INC(arg);
  629.   END;
  630.  
  631.   IF arg = 1 THEN (* no arguments passed, do the GEM stuff *)
  632.     AccentObjects.ShowTitle;
  633.     DoForms
  634.   END;
  635.  
  636.   IF NOT( CheckArgs() ) OR (nargs < 1) THEN (* show usage *)
  637.     WriteLn;
  638.     whocares := WrapWrite(' Usage: accent',FALSE);
  639.     FOR n := 0 TO HIGH(accent) DO
  640.       buf := ' -';
  641.       buf[2] := accent[n].option;
  642.       buf[3] := 0C;
  643.       Concat(buf,accent[n].descrip,buf);
  644.       whocares := WrapWrite(buf,FALSE);
  645.     END;
  646.     whocares := WrapWrite("",TRUE);
  647.     WriteLn; WriteLn;
  648.     AccentObjects.GEMTerm;
  649.   END;
  650.  
  651.   WHILE ( arg <= nargs ) DO
  652.  
  653.     (* set up initial conditions for each file *)
  654.     caps    := STARTWORD;
  655.     punc    := ASCII.LF;
  656.     pass    := FALSE;
  657.     escchar := FALSE;
  658.     ptr     := 0;
  659.  
  660.     (* go get the file *)
  661.     Assign(infile.name,args[arg]);
  662.     Lookup(infile, infile.name, FALSE);
  663.  
  664.     IF infile.res # done THEN
  665.       WriteString("Can't open file ");
  666.       WriteString(infile.name);  WaitForKey("  Press a key...  ");
  667.     ELSIF infile.new THEN
  668.       WriteString("File "); WriteString(infile.name);
  669.       WriteString(" not found");  WaitForKey("  Press a key...  ");
  670.       Delete(infile);
  671.     ELSE
  672.  
  673.       (* snarf the file into memory *)
  674.       Length(infile,infileLen);
  675.       IF infileLen >= maxFileSize THEN
  676.         n := AccentObjects.DoAlert(1,"[1][File too long][sorry]");
  677.         infileLen := 0D;
  678.       ELSE
  679.         amtToAlloc := infileLen;
  680.         Allocate(Pinfile,amtToAlloc);
  681.         IF Pinfile = NIL THEN
  682.           n := AccentObjects.DoAlert(1,"[3][Memory allocation error][arrgh]");
  683.           AccentObjects.GEMTerm;
  684.         ELSE
  685.           PinfileCH := Pinfile;
  686.           infile.buf := PinfileCH;    (* set file buffer *)
  687.           infile.buflen := infileLen; (* set file buffer length *)
  688.           SetRead(infile);            (* set read status *)
  689.           Doio(infile);               (* do the transfer *)
  690.           IF infile.res # done THEN
  691.             n := AccentObjects.DoAlert(1,"[1][Input file read error][arrgh]");
  692.             infileLen := 0D;
  693.           ELSE
  694.             GetCH;
  695.           END;
  696.           Close(infile);
  697.         END;
  698.       END;
  699.  
  700.       WHILE ( infileLen > 0D ) DO
  701.  
  702.         (* map caps to lowercase *)
  703.         IF ASCII.CharIsUpper(ch) THEN
  704.           buf[ptr] := ASCII.ToLower(ch);
  705.           INC(ptr);
  706.           IF (caps = STARTWORD) THEN caps := ALLCAPS END;
  707.           prevLF := FALSE;
  708.           GetCH;
  709.  
  710.         ELSIF ASCII.CharIsLower(ch) THEN  (* bona fide letter *)
  711.           buf[ptr] := ch; INC(ptr);
  712.           IF (caps = STARTWORD) THEN caps := NOCAPS
  713.           ELSIF (caps = ALLCAPS) THEN caps := ONECAP
  714.           END;
  715.           prevLF := FALSE;
  716.           GetCH;
  717.  
  718.         ELSE    (* check all other chars *)
  719.           IF (ch = ASCII.CR) THEN (* skip CR's *)
  720.             GetCH;
  721.           ELSIF ((ch = '.') OR (ch = "'")) AND
  722.              (nrofflag) AND
  723.              (punc = ASCII.LF) AND
  724.              (ptr = 0) THEN
  725.             pass := TRUE; (* ignore lines starting with . or ' in nroff mode *)
  726.           END;
  727.           IF ( ch = ASCII.LF ) OR
  728.              ( ch = ASCII.HT ) OR
  729.              ( ch = '.' ) OR
  730.              ( ch = ',' ) OR
  731.              ( ch = ' ' ) OR
  732.              ( ch = '!' ) OR
  733.              ( ch = '?' ) OR
  734.              ( ch = ';' ) OR
  735.              ( ch = ':' ) THEN
  736.  
  737.             punc := ch; buf[ptr] := 0C;
  738.  
  739.             (* accent individual words except, possibly, in nroff mode *)
  740.             IF (buf[0] # 0C) AND (~pass) AND (~escchar) THEN
  741.               s := 0;
  742.               WHILE (opts[s] # 0C) DO
  743.                 FOR n := 0 TO HIGH(accent) DO
  744.                   IF ( accent[n].option = opts[s] ) THEN
  745.                     accent[n].func
  746.                   END;
  747.                 END;
  748.                 INC(s);
  749.               END;
  750.             END;
  751.  
  752.             s := 0;
  753.             WHILE (buf[s] # 0C) DO (* capitalize as necessary *)
  754.               IF ASCII.CharIsAlpha(buf[s]) THEN
  755.                 IF ((caps = ONECAP) AND (s = 0)) OR (caps = ALLCAPS)
  756.                   THEN buf[s] := CAP(buf[s]) END;
  757.               END;
  758.               INC(s);
  759.             END;
  760.  
  761.             IF punc = ASCII.LF THEN (* check for paragraphs *)
  762.               IF ~prevLF THEN buf[s] := ' '; buf[s+1] := 0C END;
  763.               whocares := WrapWrite(buf,prevLF);
  764.               prevLF := TRUE;
  765.               GetCH;
  766.               IF ch = ASCII.CR THEN GetCH END;
  767.               IF ( ch = ASCII.LF ) OR
  768.                  ( ch = ASCII.HT ) OR
  769.                  ( ch = ' ' ) THEN (* yup, it's a paragraph *)
  770.                 whocares := WrapWrite("",TRUE);
  771.               END;
  772.             ELSE
  773.               buf[s] := punc;
  774.               buf[s+1] := 0C;
  775.               whocares := WrapWrite(buf,FALSE);
  776.               prevLF := FALSE;
  777.               GetCH;
  778.             END;
  779.             ptr := 0;
  780.             caps := STARTWORD;
  781.             escchar := FALSE;
  782.             (* reset pass conditions for nroff mode *)
  783.             IF (punc = ASCII.LF) THEN pass := FALSE END;
  784.  
  785.           ELSE (* not a delimiter *)
  786.             (* ignore words with escape character \ in nroff mode *)
  787.             IF (nrofflag) AND (ch = '\') THEN escchar := TRUE END;
  788.             prevLF := FALSE;
  789.             buf[ptr] := ch; INC(ptr); GetCH;
  790.           END; (* IF delimiter *)
  791.  
  792.         END; (*IF .. check char*)
  793.  
  794.       END; (* WHILE infileLen > 0D *)
  795.  
  796.       whocares := WrapWrite("",TRUE);
  797.  
  798.       DeAllocate(Pinfile,amtToAlloc);
  799.       IF redir THEN Close(outfile) END;
  800.  
  801.       INC(arg);
  802.       IF showForms THEN 
  803.         n := 0;
  804.         WHILE (n < HIGH(accent)) AND
  805.               (opts[0] # accent[n].option) DO
  806.           INC(n)
  807.         END;
  808.         opts := " *** End ";
  809.         buf := "of";
  810.         accent[n].func;
  811.         Concat(opts,buf,opts); Concat(opts,' ',opts);
  812.         buf := "file";
  813.         accent[n].func;
  814.         Concat(opts,buf,opts);
  815.         Concat(opts," ***   ",opts);
  816.         buf := "Press";
  817.         accent[n].func;
  818.         Concat(opts,buf,opts); Concat(opts,' ',opts);
  819.         buf := "a";
  820.         accent[n].func;
  821.         Concat(opts,buf,opts); Concat(opts,' ',opts);
  822.         buf := "key";
  823.         accent[n].func;
  824.         Concat(opts,buf,opts);
  825.         Concat(opts,"... ",opts);
  826.         WaitForKey(opts);
  827.         opts := "";
  828.       END;
  829.     END; (*IF infile.res*)
  830.  
  831.     IF showForms THEN
  832.       n := AccentObjects.DoAlert(1,
  833.         "[2][Would you care to have|another go at it?][Sure!|No thanks]");
  834.       IF n = 1 THEN
  835.         DoForms;
  836.         IF NOT( CheckArgs() ) THEN AccentObjects.GEMTerm END;
  837.       END;
  838.     END;
  839.  
  840.   END; (* WHILE arg <= nargs *)
  841.  
  842.   AccentObjects.GEMTerm;
  843.  
  844. END Accent.
  845.